﻿using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace YSUtils.Xml
{
	/// <summary>
	/// XML utility class.
	/// </summary>
	public static class XmlIo
	{
		#region Public methods

		/// <summary>
		/// Gets a XML document from a file.
		/// </summary>
		/// <param name="fileName">Full path to file.</param>
		/// <returns>The XML document from a file.</returns>
		public static XmlDocument GetXmlDocument(string fileName)
		{
			if (string.IsNullOrEmpty(fileName))
			{
				throw new ArgumentNullException("fileName");
			}

			if (!File.Exists(fileName))
			{
				throw new ArgumentException(String.Format(@"The ""{0}"" file doesn't exist", fileName));
			}

			XmlDocument xmlDocument = new XmlDocument();
			xmlDocument.Load(fileName);
			return xmlDocument;

		}

		/// <summary>
		/// Gets a XML document from a stream.
		/// </summary>
		/// <param name="inputStream">The input stream.</param>
		/// <returns>The XML document from a stream.</returns>
		public static XmlDocument GetXmlDocument(Stream inputStream)
		{
			if (inputStream == null)
			{
				throw new ArgumentNullException("inputStream");
			}

			XmlDocument xmlDocument = new XmlDocument();
			xmlDocument.Load(inputStream);
			return xmlDocument;
		}

		/// <summary>
		/// Getsb a XML document from a text.
		/// </summary>
		/// <param name="text">XML text.</param>
		/// <returns>The XML document from a text.</returns>
		public static XmlDocument GetXmlDocumentFromText(string text)
		{
			if (string.IsNullOrEmpty(text))
			{
				throw new ArgumentNullException("text");
			}

			XmlDocument xmlDocument = new XmlDocument();
			xmlDocument.LoadXml(text);
			return xmlDocument;
		}

		/// <summary>
		/// Gets a XElement from a file.
		/// </summary>
		/// <param name="fileName">Full path to file.</param>
		/// <returns>The XElement from a file.</returns>
		public static XElement GetXElement(string fileName)
		{
			if (string.IsNullOrEmpty(fileName))
			{
				throw new ArgumentNullException("fileName");
			}

			if (!File.Exists(fileName))
			{
				throw new ArgumentException(String.Format(@"The ""{0}"" file doesn't exist", fileName));
			}

			return XElement.Load(fileName);
		}

		/// <summary>
		/// Gets a XElement from a stream.
		/// </summary>
		/// <param name="inputStream">The input stream.</param>
		/// <returns>The XElement from a stream.</returns>
		public static XElement GetXElement(Stream inputStream)
		{
			if (inputStream == null)
			{
				throw new ArgumentNullException("inputStream");
			}

			return XElement.Load(new XmlTextReader(inputStream));
		}

		/// <summary>
		/// Gets a XElement from a text.
		/// </summary>
		/// <param name="text">The XML text.</param>
		/// <returns>The XElement from a text.</returns>
		public static XElement GetXElementFromText(string text)
		{
			if (string.IsNullOrEmpty(text))
			{
				throw new ArgumentNullException("text");
			}

			return XElement.Parse(text);
		}

		/// <summary>
		/// Puts a XML document into a file.
		/// </summary>
		/// <param name="xmlDocument">The XML document.</param>
		/// <param name="fileName">Full path to file.</param>
		/// <param name="encoding">Encoding (optional: may be null).</param>
		public static void PutXmlDocument(XmlDocument xmlDocument, string fileName, Encoding encoding)
		{
			if (xmlDocument == null)
			{
				throw new ArgumentNullException("xmlDocument");
			}

			if (string.IsNullOrEmpty(fileName))
			{
				throw new ArgumentNullException("fileName");
			}

			XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
			if (encoding != null)
			{
				xmlWriterSettings.Encoding = encoding;
			}
			XmlWriter xmlWriter = XmlWriter.Create(fileName, xmlWriterSettings);
			xmlDocument.Save(xmlWriter);
			xmlWriter.Close();
		}

		/// <summary>
		/// Puts a XML document into a stream.
		/// </summary>
		/// <param name="xmlDocument">The XML document.</param>
		/// <param name="outputStream">The output stream.</param>
		/// <param name="encoding">Encoding (optional: may be null).</param>
		public static void PutXmlDocument(XmlDocument xmlDocument, Stream outputStream, Encoding encoding)
		{
			if (xmlDocument == null)
			{
				throw new ArgumentNullException("xmlDocument");
			}

			if (outputStream == null)
			{
				throw new ArgumentNullException("outputStream");
			}

			XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
			if (encoding != null)
			{
				xmlWriterSettings.Encoding = encoding;
			}
			XmlWriter xmlWriter = XmlWriter.Create(outputStream, xmlWriterSettings);
			xmlDocument.Save(xmlWriter);
			xmlWriter.Close();
		}

		/// <summary>
		/// Puts a XML document into a string.
		/// </summary>
		/// <param name="xmlDocument">The XML document.</param>
		/// <param name="text">Receives the XML text.</param>
		public static void PutXmlDocumentToText(XmlDocument xmlDocument, out string text)
		{
			if (xmlDocument == null)
			{
				throw new ArgumentNullException("xmlDocument");
			}

			StringBuilder buffer = new StringBuilder();
			XmlWriter xmlWriter = XmlWriter.Create(buffer);
			xmlDocument.Save(xmlWriter);
			xmlWriter.Close();

			text = buffer.ToString();
		}

		/// <summary>
		/// Puts a XElement into a file.
		/// </summary>
		/// <param name="xElement">The XElement.</param>
		/// <param name="fileName">Full path to file.</param>
		/// <param name="encoding">Encoding (optional: may be null).</param>
		public static void PutXElement(XElement xElement, string fileName, Encoding encoding)
		{
			if (xElement == null)
			{
				throw new ArgumentNullException("xElement");
			}

			if (string.IsNullOrEmpty(fileName))
			{
				throw new ArgumentNullException("fileName");
			}

			XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
			if (encoding != null)
			{
				xmlWriterSettings.Encoding = encoding;
			}

			XmlWriter xmlWriter = XmlWriter.Create(fileName, xmlWriterSettings);
			xElement.Save(xmlWriter);
			xmlWriter.Close();
		}

		/// <summary>
		/// Puts a XElement into a stream.
		/// </summary>
		/// <param name="xElement">The XElement.</param>
		/// <param name="outputStream">The output stream.</param>
		/// <param name="encoding">Encoding (optional: may be null).</param>
		public static void PutXElement(XElement xElement, Stream outputStream, Encoding encoding)
		{
			if (xElement == null)
			{
				throw new ArgumentNullException("xElement");
			}

			if (outputStream == null)
			{
				throw new ArgumentNullException("outputStream");
			}

			XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
			if (encoding != null)
			{
				xmlWriterSettings.Encoding = encoding;
			}

			XmlWriter xmlWriter = XmlWriter.Create(outputStream, xmlWriterSettings);
			xElement.Save(xmlWriter);
			xmlWriter.Close();

		}

		/// <summary>
		/// Puts a XElement into a string.
		/// </summary>
		/// <param name="xElement">The XElement.</param>
		/// <param name="text">Receives the XML text.</param>
		public static void PutXElementToText(XElement xElement, out string text)
		{
			if (xElement == null)
			{
				throw new ArgumentNullException("xElement");
			}

			StringBuilder buffer = new StringBuilder();
			XmlWriter xmlWriter = XmlWriter.Create(buffer);
			xElement.Save(xmlWriter);
			xmlWriter.Close();

			text = buffer.ToString();
		}
		#endregion
	}
}
